package fileutil

import (
	"errors"
	"go-shell/src/lib/check"
	"io/fs"
	"os"
	"path/filepath"
	"strings"
)

func IsExist(path string) bool {
	_, err := os.Stat(path)
	return !os.IsExist(err)
}
func IsDir(path string) bool {
	s, err := os.Stat(path)
	if err != nil {
		return false
	}
	return s.IsDir()
}
func IsFile(path string) bool {
	return !IsDir(path)
}
func WriteFile(path string, content []byte) {
	err := os.WriteFile(path, content, 0755)
	check.CheckErrNil(err)
}

func ReadFile(path string) []byte {
	content, err := os.ReadFile(path)
	check.CheckErrNil(err)
	return content
}
func MkdirParentAll(dir string) {
	parent := filepath.Dir(dir)
	MkdirAll(parent)
}
func MkdirAll(dir string) {
	err := os.MkdirAll(dir, 0755)
	check.CheckErrNil(err)
}
func TouchFile(file string) {
	WriteFile(file, []byte(""))
}

func CopyFileToFile(source string, target string) {
	content := ReadFile(source)
	WriteFile(target, content)
}

func CopyFileToDir(source string, target string) {
	content := ReadFile(source)
	basename := filepath.Base(source)
	targetFile := filepath.Join(target, basename)
	WriteFile(targetFile, content)
}
func CopyGlobToDir(sourceRegex, target string) {
	sources, err := filepath.Glob(sourceRegex)
	if err != nil {
		panic(err)
	} else {
		for i := 0; i < len(sources); i++ {
			if IsDir(sources[i]) {
				CopyDirToDir(sources[i], target)
			} else {
				CopyFileToDir(sources[i], target)
			}
		}
	}
}
func CopyDirToDir(source string, target string) {
	sourceParent := filepath.Dir(source)
	sourceList := [][]string{}
	onWalk := func(path string, info fs.FileInfo, err error) error {
		check.CheckErrNil(err)
		relFileName, err := filepath.Rel(sourceParent, path)
		check.CheckErrNil(err)
		sourceList = append(sourceList, []string{relFileName, path})
		return nil
	}
	filepath.Walk(source, onWalk)
	for i := 0; i < len(sourceList); i++ {
		relFileName := sourceList[i][0]
		path := sourceList[i][1]
		targetPath := filepath.Join(target, relFileName)
		if IsDir(path) {
			MkdirAll(targetPath)
		} else if IsFile(path) {
			CopyFileToFile(path, targetPath)
		}
	}
}

var SPLIT_TOKEN = "/"

func Copy(source, target string) {
	if !IsExist(source) {
		panic(errors.New("source does not exist"))
	} else {
		if IsFile(source) {
			if !IsExist(target) {
				if strings.HasSuffix(target, SPLIT_TOKEN) {
					fileName := filepath.Base(source)
					target = filepath.Join(target, fileName)
					WriteFile(target, []byte{})
				} else {
					fileName := filepath.Base(source)
					target = filepath.Join(target, fileName)
					MkdirAll(target)
				}
			} else {
				if IsDir(target) {
					fileName := filepath.Base(source)
					target = filepath.Join(target, fileName)
					content := ReadFile(source)
					WriteFile(target, content)
				} else {
					content := ReadFile(source)
					WriteFile(target, content)
				}
			}
		} else if IsDir(source) {
			if !IsExist(target) {
				MkdirAll(target)
				CopyDirToDir(source, target)
			} else {
				if IsDir(target) {
					CopyDirToDir(target, source)
				} else {
					panic(errors.New("expect target is a forder, but find a file"))
				}
			}
		}
	}
}
